package com.atguigu.tingshu.common.threadPool;

import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Configuration
@EnableConfigurationProperties(ThreadProperties.class)
public class ThreadPoolConfiguration {
    @Autowired
    private ThreadProperties threadProperties;

    @Value("spring.application.name")
    private String appName;
    @Value("server.port")
    private String port;
    Logger logger = LoggerFactory.getLogger(ThreadPoolConfiguration.class);

    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        // 自定义线程工程
        ThreadFactory threadFactory = new ThreadFactory() {
            AtomicInteger atomicInteger = new AtomicInteger(0);

            @Override
            public Thread newThread(@NotNull Runnable r) {
                Thread thread = new Thread(r);
//                thread.start();// 不用继续start.线程池底层会获取自定义的线程工厂对象，然后调用newThread方法
                thread.setName(appName + "-" + port + "-" + atomicInteger.incrementAndGet());
                return thread;
            }
        };
        // 自定义拒绝策略
        RejectedExecutionHandler handler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                logger.error("提交任务：{}被自定义的拒绝策略收到", r);
                throw new RejectedExecutionException("Task " + r.toString() +
                        " rejected from " +
                        e.toString());
            }
        };
        return new ThreadPoolExecutor(threadProperties.getCorePoolSize(),
                threadProperties.getMaximumPoolSize(),
                threadProperties.getTtl(),
                threadProperties.getUnit(),
                new LinkedBlockingQueue<Runnable>(threadProperties.getBlockQueueSize()) ,
                threadFactory,
                handler);
    }
}
